package stack;

/**
 * 栈实现综合计算器
 */
public class Calculator {
    public static void main(String[] args) {
        String expression = "7*2*2-5+1-5+3-40";
        //创建数字栈
        ArrayStack2 numStack = new ArrayStack2(10);
        //创建符号栈
        ArrayStack2 operStack = new ArrayStack2(10);
        //遍历表达式
        int index = 0;
        while(index < expression.length()){
            char val = expression.charAt(index);

            if(operStack.isOper(val)){
                //说明是操作符
                if(!operStack.isEmpty()){
                    //操作符栈不是空
                    if(operStack.priority(val) <= operStack.priority((char)operStack.peak())){
                        //栈顶的优先级大于等于当前操作符的优先级，则需要将栈顶的操作符弹出，并加入到表达式中
                        char oper =(char)operStack.pop();
                        int num1 = numStack.pop();
                        int num2 = numStack.pop();
                        numStack.push(operStack.calculate(num1,num2,oper));
                        operStack.push(val);
                    }else {
                        operStack.push(val);
                    }
                }else {
                    operStack.push(val);
                }
            }else {
                int cur = index;
                //不是操作符 是操作数
                //存在问题是可能操作数不止一位
                String num = "";
                num = val+"";
                while(true){
                    if(++cur >= expression.length()){
                        break;
                    }
                    if(numStack.isOper(expression.charAt(cur))){
                        //操作数只有一位
                        break;
                    }else {
                        //操作数有多位
                        num = num + expression.charAt(cur);
                        index++;
                    }
                }
                numStack.push(Integer.parseInt(num));
                num = "";
            }
            index++;
        }
        while(!operStack.isEmpty()){
            //已经遍历完毕 但是操作符栈不为空
            char oper =(char)operStack.pop();
            int num1 = numStack.pop();
            int num2 = numStack.pop();
            numStack.push(operStack.calculate(num1,num2,oper));
        }
        System.out.println("表达式的值为："+numStack.pop());
    }
}


// 栈的数组实现
class ArrayStack2 {
    private int maxsize;// 栈的大小
    private int[] stack;// 数组模拟栈
    private int top = -1;//初始化栈顶

    public ArrayStack2(int maxsize) {
        this.maxsize = maxsize;
        stack = new int[this.maxsize];
    }

    //判断栈满
    public boolean isFull() {
        return top == maxsize - 1;
    }

    //判断栈空
    public boolean isEmpty() {
        return top == -1;
    }

    //入栈
    public void push(int value) {
        if (isFull()) {
            System.out.println("栈满");
            return;
        }
        top = top + 1;
        stack[top] = value;
        System.out.println("入栈成功,入栈元素为" + value);
    }

    //出栈
    public int pop() {
        if (isEmpty()) {
            throw new RuntimeException("栈空，不能再出栈啦~~");
        }
        int value = stack[top];
        top = top - 1;
        return value;
    }

    //遍历栈
    public void list() {
        if (isEmpty()) {
            System.out.println("栈空，没有数据~~");
            return;
        }
        for (int i = top; i >= 0; i--) {
            System.out.printf("stack[%d]=%d\n", i, stack[i]);
        }
    }

    //获取栈顶元素
    public int peak() {
        return stack[top];
    }

    //判断计算符号的优先级
    public int priority(char oper) {
        if (oper == '*' || oper == '/') {
            return 1;
        }
        if (oper == '+' || oper == '-') {
            return 0;
        }
        return -1;
    }

    //判断是否为操作符
    public boolean isOper(char val){
        return val == '+' || val == '-' || val == '*' || val == '/';
    }

    //计算方法
    /**
     * @param num1 输入的第二个数
     * @param num2 输入的第一个数
     * @param oper 操作符
     * @return
     */
    public int calculate(int num1,int num2,char oper){
        if(oper == '+'){
            return num1 + num2;
        }
        if(oper == '-'){
            return num2 - num1;
        }
        if(oper == '*'){
            return num1 * num2;
        }
        if(oper == '/'){
            return num2 / num1;
        }
        return 0;
    }
}
